系统信息采集怎么做?原生模块(native addon)的编译与多架构分发有什么坑?
考察点
- 系统信息采集方案选型
- node-gyp / prebuild / electron-rebuild 工具链
- arm64/x64 多架构分发
参考答案
1. 系统信息采集方案
(1)纯 JS 方案(首选,覆盖 80% 需求)
const os = require('os');
// Node 内置 os 模块
os.cpus(); // CPU 型号/核数
os.totalmem(); // 总内存
os.freemem(); // 空闲内存
os.platform(); // 平台
os.hostname(); // 主机名
os.networkInterfaces(); // 网卡信息
// systeminformation 库:更全面的跨平台采集
const si = require('systeminformation');
await si.cpu(); // CPU 详细信息
await si.mem(); // 内存
await si.fsSize(); // 磁盘
await si.processes(); // 进程列表(top 类功能)
await si.osInfo(); // OS 版本
await si.graphics(); // GPU/显示器
await si.battery(); // 电池
(2)Electron 特有 API
app.getAppMetrics(); // 应用各进程 CPU/内存
app.getGPUInfo('complete'); // GPU 详细信息
screen.getAllDisplays(); // 显示器信息
(3)原生模块(只有 JS 搞不定时)
- 场景:CPU 温度、风扇转速、SMART 磁盘健康、深度硬件指纹、系统级钩子
- 用 node-gyp 写 C++ addon,或引入现成的原生库
2. 设备指纹(agent 常需)
// Electron 没有官方 machineId,常见做法:
// macOS: IOPlatformUUID(ioreg 命令或原生模块)
// Windows: 注册表 MachineGuid
// 注意隐私合规:设备指纹属于敏感信息,需告知用户并脱敏传输
3. 原生模块工具链(高频踩坑区)
(1)ABI 问题:为什么普通编译的产物不能用
Node 原生模块按 ABI(Node-API 版本)编译,Electron 的 ABI 与官方 Node 不同——用系统 node 编译的 .node 文件在 Electron 里加载直接报 ABI mismatch。解决:
# 方式一:electron-rebuild(按当前 electron 版本重编译所有原生依赖)
npx electron-rebuild -f
# 方式二:node-gyp 手动指定
node-gyp rebuild --target=28.0.0 --arch=x64 --dist-url=https://electronjs.org/headers
# 方式三(推荐库作者用):N-API / node-addon-api
# N-API 是 ABI 稳定的 API 层,一次编译跨 Node/Electron 版本可用
(2)prebuildify:预编译产物分发
让用户本地编译体验极差(Windows 要装 VS Build Tools),所以原生库通常用 prebuild 分发:
releases/
├── darwin-arm64/addon.node
├── darwin-x64/addon.node
├── win32-x64/addon.node
└── linux-x64/addon.node
prebuild-install 在安装时按平台自动下载对应产物,本地编译只作为兜底。
(3)多架构 mac 包
- Apple Silicon 后需要 arm64 + x64 两个架构
- electron-builder 可以出 universal 包(合并两架构,体积约翻倍)或按架构分发
- 原生模块同样要有两架构产物,universal 打包时用
lipo合并或配置x64ArchFiles规则
4. 打包配置
{
"build": {
"asarUnpack": ["**/*.node"],
"npmRebuild": true,
"mac": { "arch": ["arm64", "x64"] }
}
}
关键坑:.node 文件必须 asarUnpack asar 包内的文件无法被 dlopen 加载(OS 需要真实文件路径),所有 .node 原生库必须解出 asar——否则开发环境正常、打包后报"module not found"。
5. 常见坑清单
- 开发正常打包挂:99% 是 asar 问题(.node 没 unpack)或 ABI 问题(rebuild 没跑)
- CI 构建:electron-rebuild 要在打包机跑,且 node 版本与项目一致;交叉编译(Mac 上编 Windows 原生模块)几乎不可行,原生模块多的项目要每平台各建一台构建机或预编译产物入库
- dll 依赖链:Windows 上 .node 还依赖其他 dll 时,要把依赖 dll 一起打包并处理加载路径
- 代码签名:macOS 公证时 .node 也要签名(见 macOS 签名篇的 library-validation)
面试话术
采集优先纯 JS(os + systeminformation),搞不定才上原生模块。原生模块的核心知识点:Electron ABI 独立所以必须 electron-rebuild;生产用 N-API + prebuild 消除版本耦合;.node 必须 asarUnpack 才能被加载;mac 多架构要 arm64/x64 双产物。交叉编译不可行,多平台原生模块要分平台构建。
常见追问
- N-API 和传统 NAN 的区别? N-API 是 Node 官方 ABI 稳定层,跨版本免重编;NAN 是社区兼容层,每次 ABI 变都要重编。新项目一律 N-API。
- 采集频率怎么定? 静态信息(CPU 型号)启动采一次;动态信息(内存/磁盘)低频周期采,高频采集本身也是资源消耗。